(function() {
if (document.readyState !== 'loading') {
    init();
} else {
    document.addEventListener('DOMContentLoaded', init);
}

function init() {

    const tabId = 'product_manage';
    let container = document.querySelector(`[data-tab-id="${tabId}"]`);
    if (!container) return;

    let $container = $(container);
    let currentHighlight = container.querySelector('.category-item');   // 分类高亮使用,刚进来默认选中第一个
    let oldCurrentHighlight = null;   // 新增根分类高亮使用
    // 保存商品列表
    let allProducts = JSON.parse(document.getElementById('products-data').textContent);

    const originalRowData = new Map();

    const headers = {
        'Content-Type': 'application/json',
        'X-CSRFToken': getCSRFToken(),
        'X-Requested-With': 'XMLHttpRequest'
    };

    // 集中缓存常用选择器(上传图片用到)
    const $elements = {
        mainImages: $('#mainImages'),
        productForm: $('#productForm'),
        productVideo: $('#productVideo'),
    };

    // 上传主图(需要的参数)
    const MAX_SIZE = 3 * 1024 * 1024; // 3MB
    const MIN_WIDTH = 640;
    const MIN_HEIGHT = 640;
    let currentCropFile = null;
    let cropper = null;

    // 上传主图(上传触发器)
    const previewContainer = document.getElementById('mainImagePreview');
    const uploadTrigger = document.getElementById('uploadTrigger');

    // 上传主图(初始化 cropModal防多层模态框卡死)
    initializeModal('#cropModal')
    // 上传主图(初始化Cropper.js)
    const cropModal = new bootstrap.Modal('#cropModal');
    const cropperImage = document.getElementById('cropperImage');

    // 上传主图(图片拖动相关参数)
    let draggedItem = null;

    // 初始化属性表
    const tableBody = document.querySelector('#attributeTable tbody');
    const detailsJson = document.getElementById('detailsJson');
    let kvData = [];
    const kvGrid = document.getElementById('kvGrid');
    // const kvEditorContainer = document.querySelector('.kv-editor-container');

    // 全局变量：存储当前预览图片列表
    let previewImages = [];
    let currentImageIndex = 0; // 当前展示的图片索引


    // ############################  监听事件 #####################################
    // 0.0.分类抽屉效果：展开/收起子分类
    container.querySelectorAll('.toggle-children').forEach(button => {
        button.addEventListener('click', function () {
            const icon = this.querySelector('i');
            if (icon.classList.contains('bi-caret-right-fill')) {
                icon.classList.replace('bi-caret-right-fill', 'bi-caret-down-fill');
            } else {
                icon.classList.replace('bi-caret-down-fill', 'bi-caret-right-fill');
            }
        });
    });

    // 0.1. 点击分类名显示关联商品
    $(container).off('click', '.category-item')
        .on('click', '.category-item', function (e) {
            // 关闭所有已展开的下拉菜单
            $('.dropdown', container).each(function () {
                const $dropdown = $(this);
                const $menu = $dropdown.find('.dropdown-menu');
                const $button = $dropdown.find('.dropdown-toggle');
                if ($menu.length && $button.length &&
                    !$dropdown.is(e.target) &&
                    !$dropdown.has(e.target).length &&
                    $menu.hasClass('show')) {
                    $button.attr('aria-expanded', 'false');
                    $menu.removeClass('show');
                }
            });
            categoryToProduct(e);
        });

    // 1. 新增根分类
    $(container).off('click', '#addCategoryBtn')
        .on('click', '#addCategoryBtn', addNewCategoryRow);

    // 2. 分类编辑操作  3. 分类删除操作  4. 新增子分类
    $(container).off('click', '.dropdown-item[data-action]')
        .on('click', '.dropdown-item[data-action]', function (e) {
            e.preventDefault();
            const [action, categoryId] = $(this).data('action').split('-');
            switch (action) {
                case 'edit':
                    editCategory(e);
                    break; // 2.分类:编辑
                case 'delete':
                    deleteCategory(e, categoryId);
                    break; //3.删除
                case 'add':
                    addSubcategory(e, categoryId);
                    break; //4.新增子分类
            }
        });

    // 5. 分类保存按钮
    $(container).off('click', '.save-category')
        .on('click', '.save-category', saveCategory);

    // 6. 分类编辑取消
    $(container).off('click', '.cancel-category')
        .on('click', '.cancel-category', cancelCategoryEdit);

    // 7.保存子分类
    $(container).off('click', '.save-subcategory')
        .on('click', '.save-subcategory', saveSubcategory);

    // 8.作废子分类
    $(container).off('click', '.cancel-subcategory')
        .on('click', '.cancel-subcategory', function (e) {
            $(this).closest('.subcategory-editor').remove();
            oldCurrentHighlight = null;
        });

    // 9. 新增商品
    $(container).off('click', '#addProductBtn')
        .on('click', '#addProductBtn', function () {
            addOrEditProduct()
        });

    // 10. 商品图片预览
    $(container).off('click', '[data-tab-id] .img-thumbnail')
        .on('click', '[data-tab-id] .img-thumbnail', previewPictures);

    // 11. 商品行编辑修改
    $(container).off('click', '.edit-product')
        .on('click', '.edit-product', editProductRow);

    // 12. 商品删除(未调试)
    $(container).off('click', '.delete-product')
        .on('click', '.delete-product', deleteProduct);

    // 13. 商品状态切换(未调试)
    $(container).off('click', '.toggle-status')
        .on('click', '.toggle-status', toggleProductStatus);

    // 14. 商品搜索(未调试)
    $(container).off('click', '#searchBtn')
        .on('click', '#searchBtn', searchProducts);

    // 15.商品表单提交处理(未调试)
    $(container).off('click', '#submitProductBtn')
        .on('click', '#submitProductBtn', submitProductForm);

    // 16. 新增或修改商品之:+历史属性值,不能绑在$(container),因是模态框,没有打开就没有绑定
    $('#addAttribute').off('click').on('click', historicalAttribute);

    // 17.新增或修改商品之:+自添属性值
    $('#customizeAttribute').off('click').on('click', addNewRow);

    // 18.新增或修改商品之:-删除属性值对
    $('#kvGrid').off('click').on('click', deleteRow);

    // 19. 新增或修改商品之:点击"查看示例"
    $('#showExample').off('click').on('click', viewExamples);

    // 20.上传主图
    // $elements.mainImages.off('change').on('change', uploadMainImage);
    $('#uploadTrigger').off('click').on('click', () => $elements.mainImages[0].click());
    $elements.mainImages.off('change').on('change', handleFileSelect);

    // 20-1.上传主图:裁剪图片->旋转按钮事件
    $('#rotateLeft').off('click').on('click',function () {cropper.rotate(-90)});

    // 20-2.上传主图:裁剪图片->旋转按钮事件
    $('#rotateRight').off('click').on('click',function () {cropper.rotate(90)});

    // 20-3.上传主图:裁剪图片->删除图片事件
    $('#deleteImage').off('click').on('click',function (e) {
        e.preventDefault(); // 阻止默认行为(模态框关闭时,不会触发到表单的默认行为)
        currentCropFile.previewItem.remove();
        cropModal.hide();
    });

    // 20-4.上传主图:裁剪图片->确认裁剪事件
    $('#confirmCrop').off('click').on('click', confirmCrop);

    // 20-5.上传主图:裁剪图片->关闭事件
    $('#cropModal').off('click','.btn-close, .btn-secondary')
        .on('click','.btn-close, .btn-secondary', function (e) {
             currentCropFile.previewItem.remove()
        });

    // 21.视频上传功能
    $elements.productVideo.off('change').on('change', uploadVideo);


    // ############################  事件相关函数 #####################################
    //0.点击分类名,右侧出现关联的商品列表
    function categoryToProduct(e) {
        e.preventDefault(); // 阻止默认跳转
        e.stopPropagation();  // 阻止事件冒泡（双重保险）
        // 兼容旧版 IE
        if (typeof e.preventDefault !== 'function') {
            e.returnValue = false;
        }
        if (['作废', '保存', '修改名称', '删除此类', '添加子类'].includes(e.target.textContent.trim())) return

        // 0. 移除旧高亮
        if (currentHighlight) {
            currentHighlight.classList.remove('table-danger');
        } else {
            container.querySelector('.category-item').classList.remove('table-danger')
        }
        // 1. 高亮选中分类
        const li = e.target.closest('.category-item')
        li.classList.add('table-danger');
        currentHighlight = li;
        // 2. 获取分类ID（从URL参数解析）
        const aTag = li.querySelector('a.category-name');
        const categoryId = new URL(aTag.href).searchParams.get('category_id');
        const categoryName = aTag.textContent.trim()

        // 3. 使用Fetch API发送请求
        // fetch(`/ecom/product/products/?category_id=${categoryId}`, {
        fetch(`/ecom/product/manage/?category_id=${categoryId}`, {
            method: 'GET',
            headers: headers
        })
            .then(response => {
                if (!response.ok) throw new Error('网络响应异常');
                return response.json();
            })
            .then(data => {
                // 4. 清空现有表格内容
                const tbody = document.querySelector('table tbody');
                tbody.innerHTML = '';
                document.querySelector('.product-title').textContent = '[' + categoryName + '] 商品'
                // 保存起来做为以后单条记录修改时调用
                allProducts = data.products;

                showPage(data, $container)  // 分页,再完善

                // 5.判断商品数据是否为空
                if (!data.products || data.products.length === 0) {
                    // 5.1 显示"没有关联商品"提示
                    tbody.innerHTML = `
                    <tr>
                      <td colspan="7" class="text-center" style="height: 63vh; border: none">
                        <div class="text-muted">
                          <i class="bi bi-exclamation-circle fs-1"></i>
                          <h5 class="mt-3">[${categoryName}]下没有关联商品</h5>
                          <p class="small mt-2">
                            <a href="#" class="text-decoration-none">添加新商品</a>
                            或
                            <a href="#" class="text-decoration-none">浏览其他分类</a>
                          </p>
                        </div>
                      </td>
                    </tr>
                  `;
                } else {
                    // 5.2 有商品时正常渲染,动态生成新商品行
                    data.products.forEach(product => {
                        const statusClass = product.is_active ? 'success' : 'secondary';
                        const statusText = product.is_active ? '上架' : '下架';
                        const btnClass = product.is_active ? 'secondary' : 'success';
                        const btnText = product.is_active ? '下架' : '上架';

                        const row = `
                            <tr data-product-id="${product.id}">
                              <td>${product.id}</td>
                              <td>
                                ${product.main_images ?
                            `<img src="${product.main_images[0].src}" class="img-thumbnail" width="40">` :
                            `<div class="bg-light border rounded" style="width:40px;height:40px"></div>`}
                              </td>
                              <td title="${product.name}">${product.name}</td>
                              <td>${product.stock}</td>
                              <td>¥${product.price}</td>
                              <td>
                                <span class="badge bg-${statusClass}">${statusText}</span>
                              </td>
                              <td>
                                <button class="btn btn-sm btn-warning edit-product">修改</button>
                                <button class="btn btn-sm btn-danger delete-product">删除</button>
                                <button class="btn btn-sm btn-${btnClass} toggle-status">${btnText}</button>
                              </td>
                            </tr>`;

                        tbody.insertAdjacentHTML('beforeend', row);
                    });
                }
            })
            .catch(error => console.error('请求失败:', error));
    }

    // 1.新增根分类
    function addNewCategoryRow() {
        if (oldCurrentHighlight) {
            showToast('请先完成已有编辑行', 'warning', 'top');
            return
        }
        const newRow = `<li class="list-group-item d-flex flex-column p-0 category-item">
               <div class="d-flex justify-content-between align-items-center w-100 py-2 px-3"> 
                 <div class="d-flex align-items-center flex-grow-1 min-width-0 pe-2">   
                    <input type="text" class="form-control form-control-sm new-category-input w-100" placeholder="输入分类名称">
                 </div>        
                 <div class="flex-shrink-0 dropdown">
                    <button class="btn btn-sm btn-success save-category">保存</button>
                    <button class="btn btn-sm btn-warning cancel-category ms-1">作废</button>
                 </div>
               </div>              
            </li>`;
        // 先把当前选中保存,已备新增作废时恢复
        oldCurrentHighlight = currentHighlight
        // 0. 移除旧高亮
        if (currentHighlight) {
            currentHighlight.classList.remove('table-danger');
        } else {
            container.querySelector('.category-item').classList.remove('table-danger')
        }
        const $this = $('#categoryList')
        $this.prepend(newRow);     // 增加在前面
        $this.closest('div').scrollTop(0); // 滚动到容器顶部
        // 获取原生 DOM
        const domRow = $this.children()[0];
        // 先添加选中高亮
        $(domRow).addClass('table-danger');

        currentHighlight = domRow
        // 添加编辑状态视觉反馈
        $(domRow).addClass('editing');

        // 绑定点击事件
        const input = domRow.querySelector('input')
        // 阻止事件冒泡
        input.addEventListener('click', function (e) {
            e.stopPropagation();
        });
        // 防止焦点事件冒泡（额外保护）
        input.addEventListener('focus', function (e) {
            e.stopPropagation();
        });
        input.focus()
    }

    // 2.分类名称:编辑
    function editCategory(e) {
        if (oldCurrentHighlight) {
            showToast('请先完成已有编辑行', 'warning', 'top');
            return
        }
        const li = e.target.closest('.category-item')
        // const categoryId = li.dataset.categoryId || ''
        // const parentId = li.querySelector('ul').dataset.parentId || ''
        // 保存原始状态（用于取消时恢复）
        const categoryNameLink = li.querySelector('.category-name');
        // const originalHtml = categoryNameLink.innerHTML;
        const originalName = categoryNameLink.textContent.trim();

        // 设置数据属性以便恢复
        // li.dataset.originalHtml = originalHtml;
        li.dataset.originalName = originalName;
        li.dataset.liHtml = li.innerHTML;

        // 先把当前选中保存,已备新增作废时恢复
        oldCurrentHighlight = currentHighlight

        // 创建输入框
        const input = document.createElement('input');
        input.type = 'text';
        input.className = 'form-control form-control-sm new-category-input w-100';
        input.value = originalName;

        // 替换链接为输入框
        categoryNameLink.replaceWith(input);

        // 替换按钮
        const buttonsContainer = li.querySelector('.flex-shrink-0.dropdown');

        buttonsContainer.innerHTML = `
        <button class="btn btn-sm btn-success save-category">保存</button>
        <button class="btn btn-sm btn-warning cancel-category ms-1">作废</button>
         `;
        // 添加编辑状态视觉反馈
        li.classList.add('editing');

        // 绑定点击事件
        input.addEventListener('click', function (e) {
            e.stopPropagation(); // 阻止事件冒泡
        });
        // 绑定聚焦事件（额外保护）
        input.addEventListener('focus', function (e) {
            e.stopPropagation(); // 防止焦点事件冒泡
        });

        // 自动聚焦输入框
        input.focus();
    }

    // 3.分类:删除
    function deleteCategory(e, categoryId) {
        if (oldCurrentHighlight) {
            showToast('请先完成已有编辑行', 'warning', 'top');
            return
        }
        const li = e.target.closest('li.category-item')
        // 精确获取分类名称（排除按钮文本）
        const categoryName = $(li).find('.category-name').text().trim();
        // 高亮
        $(li).addClass('table-danger').siblings().removeClass('table-danger');
        Swal.fire({
            title: '确认删除',
            text: `确定要删除分类 "${categoryName}" 吗？此操作不可恢复。`,
            icon: 'warning',
            showCancelButton: true,
            confirmButtonColor: '#d33',
            cancelButtonColor: '#3085d6',
            confirmButtonText: '确认删除',
            cancelButtonText: '取消'
        }).then((result) => {
            if (result.isConfirmed) {
                fetch(`/ecom/product/categories/${categoryId}/`, {
                    method: 'DELETE',
                    headers: headers,
                })
                    .then(response => {
                        if (!response.ok) {
                            return response.json().then(errorData => {
                                // 抛出包含后端错误信息的自定义错误
                                throw new Error(
                                    errorData.message ||
                                    errorData.error ||
                                    `HTTP ${response.status}: ${response.statusText}`
                                );
                            });
                        }
                        return response.json();
                    })
                    .then(data => {
                        $(li).remove()
                        showToast(`分类"${categoryName}"已删除`, 'success', 'top');
                        oldCurrentHighlight = null
                        // 更换层级图标
                        if (data.parent_id) {
                            const ownLi = container.querySelector(`li[data-category-id="${data.parent_id}"]`) || ''
                            const sonLi = ownLi.querySelector('.category-item') || ''
                            if (!sonLi) {
                                const icon = ownLi.querySelector('button.toggle-children i');
                                if (icon) {
                                    icon.className = 'bi bi-folder-fill me-1 text-primary'
                                }
                            }
                        }
                    })
                    .catch(error => {
                        console.log('删除失败:', error.message)
                        showToast(`删除失败: ${error.message}`, 'error', 'top');
                    });
            } else {
                // 移除高亮
                $(li).removeClass('table-danger');
            }
        });
    }

    // 4.添加子分类
    function addSubcategory(e, categoryId) {
        e.preventDefault();
        e.stopPropagation()
        if (oldCurrentHighlight) {
            showToast('请先完成已有编辑行', 'warning', 'top');
            return
        }
        // 先把当前选中保存,已备新增作废时恢复
        oldCurrentHighlight = currentHighlight
        // 0. 移除旧高亮
        if (currentHighlight) {
            currentHighlight.classList.remove('table-danger');
        } else {
            container.querySelector('.category-item').classList.remove('table-danger')
        }
        const li = e.target.closest('li.list-group-item');
        const $currentRow = $(li);

        // 下拉框老要出来,加这个让它回去
        if (li.querySelector('.dropdown-toggle').getAttribute('aria-expanded') === 'true') {
            li.querySelector('.dropdown-toggle').click();
        }

        // 防止重复添加
        if ($currentRow.next('.subcategory-editor').length) return;

        // 计算缩进量
        const currentIndent = parseInt($currentRow.css('padding-left')) || 0;
        const newIndent = currentIndent + 30; // 增加30px缩进

        // 创建编辑行
        const editorRow = `
            <li class="list-group-item d-flex justify-content-between align-items-center subcategory-editor"
                data-parent-id="${categoryId}" 
                style="padding-left: ${newIndent}px;">
                <div class="d-flex align-items-center flex-grow-1 min-width-0 pe-2 new-subcategory-div">
                    <input type="text" class="form-control form-control-sm new-subcategory-input" placeholder="输入子分类名称">
                </div>
                <div class="flex-shrink-0 dropdown">
                    <button class="btn btn-sm btn-success save-subcategory">保存</button>
                    <button class="btn btn-sm btn-warning cancel-subcategory ms-1">作废</button>
                </div>
            </li>`;

        // 插入到当前行下方
        $currentRow.after(editorRow);

        const domRow = $currentRow.next();
        // 先添加选中高亮
        $currentRow.addClass('table-danger');

        currentHighlight = li
        // 添加编辑状态视觉反馈
        $(domRow).addClass('editing');

        // 绑定点击事件
        const input = domRow.find('input')
        // 使用jQuery的on()方法绑定事件
        input.on('click', function (e) {
            e.stopPropagation(); // 阻止click事件冒泡
        }).on('focus', function (e) {
            e.stopPropagation(); // 阻止focus事件传播
        }).focus(); // 触发焦点``

    }

    // 5.分类:保存(新增或者修改)
    function saveCategory(e) {
        const li = e.target.closest('li')
        const parentLi = li.parentElement.closest('.category-item');
        const input = li.querySelector('.new-category-input');
        const name = input.value.trim();
        const categoryId = li.dataset.categoryId || '';      // 自己id
        const parentId = parentLi ? parentLi.dataset.categoryId : '';  // 父级id

        if (!name) {
            showToast('分类名称不能为空', 'warning', 'top');
            return;
        }

        const body = categoryId
            ? {id: categoryId, parent_id: parentId, name: name}
            : {parent_id: parentId, name: name};

        fetch('/ecom/product/categories/', {
            method: 'POST',
            body: JSON.stringify(body),
            headers: headers,
            credentials: 'include' // 包含 cookies
        })
            .then(response => {
                if (!response.ok) {
                    return response.json().then(errorData => {
                        // 抛出包含后端错误信息的自定义错误
                        throw new Error(
                            errorData.message ||
                            errorData.error ||
                            `HTTP ${response.status}: ${response.statusText}`
                        );
                    });
                }
                return response.json();
            })
            .then(data => {
                showToast('保存成功:', 'success', 'top');
                const returnCategoryId = data.id
                const returnCategoryName = data.name

                // 创建原始链接
                const link = document.createElement('a');
                link.href = `?category_id=${returnCategoryId}`;
                link.className = 'text-decoration-none text-dark category-name';
                link.title = returnCategoryName;
                link.dataset.parentId = returnCategoryId

                li.dataset.categoryId = returnCategoryId

                // 先添加图标(没有时,就添加一级分类图标)
                const originIcon = li.querySelector('i')
                if (!originIcon) {
                    const icon = document.createElement('i');
                    icon.className = 'bi bi-folder-fill me-2 text-primary';
                    link.appendChild(icon);
                }
                // 添加文本(不破坏DOM)
                const textNode = document.createTextNode(returnCategoryName);
                link.appendChild(textNode);

                // 替换输入框为原始链接
                input.replaceWith(link);

                // 恢复原始按钮
                const buttonsContainer = li.querySelector('.flex-shrink-0.dropdown');
                buttonsContainer.innerHTML = `
                  <button class="btn btn-sm btn-light dropdown-toggle border-0 shadow-sm"
                          type="button"
                          data-bs-toggle="dropdown"
                          aria-expanded="false"
                          style="background: linear-gradient(to bottom, #ffffff, #f8f9fa)">
                    操作
                  </button>
                  <ul class="dropdown-menu dropdown-menu-end shadow-sm p-1"
                      style="min-width: fit-content; border-radius: 0.375rem">
                    <li><a class="dropdown-item px-3 py-2" href="#" data-action="edit-${returnCategoryId}">修改名称</a></li>
                    <li><a class="dropdown-item px-3 py-2" href="#" data-action="delete-${returnCategoryId}">删除此类</a></li>
                    <li><hr class="dropdown-divider my-1"></li>
                    <li><a class="dropdown-item px-3 py-2" href="#" data-action="add-${returnCategoryId}">添加子类</a></li>
                  </ul>
              `;
                // 移除编辑状态
                li.classList.remove('editing');
                // 恢复新增时备用的高亮
                oldCurrentHighlight = null
                // 清除临时存储的数据
                delete li.dataset.originalName;
                delete li.dataset.liHtml;
                // 如果是新增分类
                if (!categoryId) {
                    // 4. 清空现有表格内容
                    const tbody = document.querySelector('table tbody');
                    tbody.innerHTML = '';
                    document.querySelector('.product-title').textContent = '[' + returnCategoryName + '] 商品'
                    // 显示"没有关联商品"提示
                    tbody.innerHTML = `
                    <tr>
                      <td colspan="7" class="text-center" style="height: 63vh; border: none">
                        <div class="text-muted">
                          <i class="bi bi-exclamation-circle fs-1"></i>
                          <h5 class="mt-3">[${returnCategoryName}]下没有关联商品</h5>
                          <p class="small mt-2">
                            <a href="#" class="text-decoration-none">添加新商品</a> 
                            或 
                            <a href="#" class="text-decoration-none">浏览其他分类</a>
                          </p>
                        </div>
                      </td>
                    </tr>
                  `;

                }
            })
            .catch(error => {
                showToast(`保存失败: ${error.message}`, 'error', 'top');
            })
            .finally(() => {
                oldCurrentHighlight = null
            })
        ;
    }

    // 6.分类:作废
    function cancelCategoryEdit(e) {
        const li = e.target.closest('.category-item')
        // 新增直接删除
        if (!li.getAttribute('data-category-id')) {
            if (oldCurrentHighlight) {
                oldCurrentHighlight.classList.add('table-danger');
                currentHighlight = oldCurrentHighlight
                oldCurrentHighlight = null
            }
            li.remove();
            return
        }
        // 恢复原始HTML
        if (li.dataset.liHtml) {
            li.innerHTML = li.dataset.liHtml;
        }
        // 移除编辑状态
        li.classList.remove('editing');
        // 清除临时存储的数据
        // delete li.dataset.originalHtml;
        delete li.dataset.originalName;
        delete li.dataset.liHtml;
        oldCurrentHighlight = null
        // 下拉框老要出来,加这个让它回去
        if (li.querySelector('.dropdown-toggle').getAttribute('aria-expanded') === 'true') {
            li.querySelector('.dropdown-toggle').click();
        }
    }

    // 7.保存子分类:之保存到后端
    function saveSubcategory(e) {
        const $editorRow = $(e.target.closest('.subcategory-editor'));
        const parentId = $editorRow.data("parent-id") || '0';
        const name = $editorRow.find('.new-subcategory-input').val().trim();

        if (!name) {
            showToast('请输入分类名称', 'warning', 'top');
            return;
        }

        $.ajax({
            url: '/ecom/product/categories/add_subcategory/',
            method: 'POST',
            dataType: 'json',
            data: {
                name: name,
                parent_id: parentId,
                csrfmiddlewaretoken: getCSRFToken(),   //'{{ csrf_token }}'
            },
            success: function (response) {
                if (response.success) {
                    showToast('子分类添加成功', 'success', 'top')
                    // 刷新分类列表或动态添加新项
                    addNewCategoryItem(response, $editorRow)
                    oldCurrentHighlight = null

                } else {
                    showToast('保存失败: ' + response.error, 'error', 'top');
                }
            },
            error: function (error) {
                showToast('请求失败，请重试', 'error', 'top');
            }
        });

    }

    // 8.作废子分类(包含在上边点击事件了)

    //9.新增或修改商品(模态框)
    function addOrEditProduct(productId = null) {
        const productIdList = productId ? allProducts.filter(product => product.id === productId) : [];
        let productCategories
        // 动态切换 inert 状态(去除警告,焦点回归正常作用)
        modalInert('#addProductModal')
        // 先清空表单
        resetProductForm();
        // 填充数据
        if (productIdList[0]) {
            productCategories = productIdList[0].categories
            fillProductForm(productIdList[0]);
            // 编辑模式
            $elements.productForm.data('product-id', productId);
            $('.modal-title').first().text('编辑商品');
            $('#submitProductBtn').text('更新商品');
        } else {
            // 新增模式
            productCategories = []
            $elements.productForm.removeData('product-id');
            $('.modal-title').first().text('新增商品');
            $('#submitProductBtn').text('保存商品');
        }
        // 请求分类信息
        fetch('/ecom/product/product_category/')
            .then(response => response.json())
            .then(data => {
                initCategoryTree(data, productCategories || [])
            })
        // 初始化模态框
        const addProductModal = new bootstrap.Modal(document.getElementById('addProductModal'));
        addProductModal._config.keyboard = false; // 禁用ESC
        addProductModal.show();
    }

    // 10. 预览商品图片(商品行的主图)
    function previewPictures(e) {
        e.preventDefault();
        const row = e.target.closest('tr')
        const productId = row.dataset.productId
        const product = allProducts.find(item => item.id === parseInt(productId));
        if (product) {
            previewImages = []
            currentImageIndex = 0
            product.main_images.forEach(imageData => {
                previewImages.push(imageData);
            })
        } else {
            console.log("未找到该商品");
        }
        // 更新计数器
        updateImageCounter();

        // 设置模态框内容
        document.getElementById('previewImage').src = previewImages[0].src;
        // 让模态框焦点回归正常
        modalInert('#imagePreviewModal')
        // 初始化模态框
        const imagePreviewModal = new bootstrap.Modal('#imagePreviewModal');
        // 显示模态框
        imagePreviewModal.show();
    }

    // 11.商品行编辑(修改)
    function editProductRow(e) {
        const row = e.target.closest('tr');
        const productId = $(row).data('product-id');
        addOrEditProduct(productId)

        // 1. 保存原始数据
        // saveOriginalData(row);

        // 获取当前行数据
        // const name = row.find('td:eq(2)').text();
        // const stock = row.find('td:eq(3)').text();
        // const price = row.find('td:eq(4)').text().replace('¥', '');

        // 转换为编辑模式
        // row.find('td:eq(2)').html(`<input class="form-control form-control-sm" value="${name}">`);
        // row.find('td:eq(3)').html(`<input type="number" class="form-control form-control-sm" value="${stock}" min="0">`);
        // row.find('td:eq(4)').html(`<input type="number" step="0.01" class="form-control form-control-sm" value="${price}">`);

        // 更新操作按钮
        // const statusBtn = row.find('.toggle-status').clone();
        //
        // row.find('td:last-child').html(`
        //     <button class="btn btn-sm btn-success save-edit">保存</button>
        //     <button class="btn btn-sm btn-secondary cancel-edit">作废</button>
        //   `).append(statusBtn);
        //
        // // 4. 绑定保存事件
        // row.find('.save-edit').click(function () {
        //     // saveProductEdit(productId);  // saveProduct()
        //     console.log('到保存这里')
        // });
        //
        // // 5. 绑定作废事件
        // row.find('.cancel-edit').click(function () {
        //     restoreOriginalData(row, productId);
        // });
    }

    // 12. 商品删除
    function deleteProduct(e) {
        const row = e.target.closest('tr');
        const productId = $(row).data('product-id');
        console.log('到商品删除这里了productId:', productId)
    }

    // 13. 商品上下架状态切换
    function toggleProductStatus() {
        const productId = $(this).closest('tr').data('product-id');
        $.post(`/api/products/${productId}/toggle_status/`, function (response) {
            if (response.success) {
                // loadProducts(); // 刷新列表
            }
        });
    }

    // 14. 商品搜索
    function searchProducts(keyword) {
        // 根据关键词异步搜索 [[19, 17]]
        $.ajax({
            url: '/api/products/search',
            method: 'POST',
            data: {keyword: keyword},
            success: (results) => {
                // renderProductList(results);  // 渲染搜索结果
            },
            error: (error) => {
                console.error("搜索失败:", error);
            }
        });
    }

    // 15.商品表单提交处理(暂未用)
    function submitProductForm() {
        const formData = new FormData($elements.productForm[0]);
        const productId = $elements.productForm.data('product-id');

        if (productId) {
            formData.append('product_id', productId);
        }

        $.ajax({
            url: productId ? '/api/products/update/' : '/api/products/create/',
            type: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            success: function (response) {
                // 处理成功响应
                bootstrap.Modal.getInstance('#addProductModal').hide();
                showSuccessToast(productId ? '商品更新成功' : '商品添加成功');
                refreshProductList();
            },
            error: function (xhr) {
                showErrorToast(xhr.responseJSON?.message || '操作失败');
            }
        });
    }

    // 16. 新增或修改商品之:+历史属性值
    function historicalAttribute() {
        fetch('/ecom/product/product/attributes/')
            .then(response => response.json())
            .then(data => {
                // 存储键值对数据
                kvGrid.innerHTML = '';
                kvData = data
                renderGrid(data);
            })
    }

    // 17.新增或修改商品之:+自添属性值
    function addNewRow() {
        renderGrid(kvData);
        // 聚焦到新行的键输入框
        const newRow = kvGrid.lastChild;
        const keyInput = newRow.querySelector('.kv-key input');
        setTimeout(() => keyInput.focus(), 10);
    }

    // 18.新增或修改商品之:-删除属性值对
    function deleteRow(e) {
        const deleteBtn = e.target.closest('.remove-btn');
        if (deleteBtn) {
            removeRow(e)
        }
    }

    // 19. 新增或修改商品之:点击"查看示例"
    function viewExamples() {
        // 初始化 exampleModal避免多层模态框界面卡死
        initializeModal('#exampleModal')
        new bootstrap.Modal(document.getElementById('exampleModal')).show();
    }

    // 20.上传主图(处理选择的文件)
    function handleFileSelect(e) {
        const files = Array.from(e.target.files);
        // 图片列表归零
        currentImageIndex = 0

        files.forEach(file => {
            // 验证文件类型
            if (!['image/jpeg', 'image/png'].includes(file.type)) {
                showAlert('仅支持JPG/PNG格式', 'danger');
                return;
            }

            // 验证文件大小
            if (file.size > MAX_SIZE) {
                showAlert('图片大小不能超过3MB', 'danger');
                return;
            }

            // 创建预览项
            // const previewItem = createPreviewItem(file);
            const previewItem = createPreviewItem();
            previewContainer.insertBefore(previewItem, uploadTrigger);

            // 读取图片尺寸
            const reader = new FileReader();
            reader.onload = function(e) {
            const img = new Image();

            img.onload = function() {
                // 验证图片尺寸
                if (img.width < MIN_WIDTH || img.height < MIN_HEIGHT) {
                    previewItem.querySelector('.preview-error').textContent = `尺寸不足 ${img.width}x${img.height}`;
                    previewItem.classList.add('border-danger');
                    // 裁剪对话框
                    showCropDialog(previewItem, file, e.target.result);
                } else {
                    // 尺寸合格，直接显示
                    const imgElement = previewItem.querySelector('img');
                    imgElement.src = e.target.result;
                    imgElement.id = Date.now() + Math.random().toString(36).substr(2, 9);
                    // 模拟上传进度条
                    simulateUploadProgress(previewItem);
                    // 放入总的预览列表中
                    previewImages.push(imgElement);
                }

            };
            img.src = e.target.result;
        };
            reader.readAsDataURL(file);
            // 重置文件输入（允许再次选择相同文件）
            this.value = '';
        });

    }

    // 21.视频上传功能
    function uploadVideo(e) {
        const file = e.target.files[0];
        if (!file) return;
        // 显示上传提示
        document.getElementById('uploadVideoAlert').classList.remove('d-none');
        // 创建预览
        const previewDiv = document.getElementById('videoPreview');
        previewDiv.innerHTML = '';

        const videoElement = document.createElement('video');
        videoElement.setAttribute('controls', 'true');
        videoElement.style.maxWidth = '100%';
        videoElement.style.maxHeight = '300px';

        // const videoURL = URL.createObjectURL(file);
        videoElement.src = URL.createObjectURL(file);

        previewDiv.appendChild(videoElement);

        // 隐藏上传提示（实际项目中需在AJAX上传完成后执行）
        setTimeout(() => {
            document.getElementById('uploadVideoAlert').classList.add('d-none');
        }, 1000);
    }


    // ############################  函数相关辅助函数 #####################################
    // 辅助函数7.保存子分类->保存到后端->动态刷新子分类
    function addNewCategoryItem(response, li) {
        const newCategory = response.new_category;
        const parentId = newCategory.parent_id
        const ownId = newCategory.id

        const parentContainer = $(`[data-category-id="${parentId}"]`);

        // 更新父节点状态
        parentContainer.attr('data-has-children', 'true');

        // 追加新节点
        const newItem = renderCategory(newCategory, null, parseInt(parentContainer.attr('data-level')) + 1);

        // 尝试查找现有的子分类容器
        const $childrenContainer = parentContainer.find('> .children-container > ul');

        if ($childrenContainer.length === 0) {
            // 1. 创建新的子分类容器结构
            const newContainer = $(`
                <div class="collapse children-container w-100" id="children-${ownId}">
                    <ul class="list-group list-group-flush children-list ps-4"
                        data-parent-id="${ownId}">
                    </ul>
                </div>
            `);

            // 2. 将新容器添加到父元素中
            parentContainer.append(newContainer);

            const toggleBtn = `
            <button class="btn btn-sm btn-link p-0 me-1 toggle-children"
                    type="button"
                    data-bs-toggle="collapse"
                    data-bs-target="#children-${ownId}"
                    aria-expanded="true"
                    aria-controls="children-${ownId}">
              <i class="bi bi-caret-right-fill"></i>
            </button>`;
            parentContainer.find('.category-name i').remove();
            // 2. 在 .category-name 之前插入 toggleBtn
            parentContainer.find('.category-name').before(toggleBtn);
        }
        parentContainer.find(`> .children-container > ul`).append(newItem);

        $(li).remove()

        if (!parentContainer.find('.collapse.show').length) {
            // 1. 定位按钮元素
            const $button = parentContainer.find('button.toggle-children');
            // 2. 设置 aria-expanded 属性
            $button.attr('aria-expanded', 'true').trigger('click');
        }
        // 8. 恢复状态
        // $(li).removeClass('editing');
        oldCurrentHighlight = null;
    }

    // 辅助函数7.保存子分类->保存到后端->动态刷新子分类->分类节点渲染函数
    function renderCategory(category, selectedId, level = 0) {
        const hasChildren = category.children && category.children.length > 0;
        // 缩进样式（参考的层级缩进方案）
        const indentStyle = level > 0 ? `style="padding-left: ${level * 20 + 5}px"` : '';

        return `
      <li class="list-group-item d-flex flex-column p-0 category-item ${category.id === selectedId ? 'table-danger' : ''}"
          data-category-id="${category.id}"
          data-has-children="${hasChildren}"
          ${indentStyle}>
        <div class="d-flex justify-content-between align-items-center w-100 py-2 px-3">
          <div class="d-flex align-items-center flex-grow-1 min-width-0 pe-2">
            ${hasChildren ? `
              <button class="btn btn-sm btn-link p-0 me-1 toggle-children"
                      type="button"
                      data-bs-toggle="collapse"
                      data-bs-target="#children-${category.id}">
                <i class="bi bi-caret-right-fill"></i>
              </button>` : ''
        }
            <a href="?category_id=${category.id}" class="text-decoration-none text-dark category-name">
              ${!hasChildren ? `<i class="bi bi-folder-fill me-1 text-primary"></i>` : ''}
              ${category.name}
            </a>
          </div>
          <div class="flex-shrink-0 dropdown">
            <button class="btn btn-sm btn-light dropdown-toggle border-0 shadow-sm"
                    type="button"
                    data-bs-toggle="dropdown">
              操作
            </button>
            <ul class="dropdown-menu dropdown-menu-end shadow-sm p-1">
              <li><a class="dropdown-item px-3 py-2" href="#" data-action="edit-${category.id}">修改名称</a></li>
              <li><a class="dropdown-item px-3 py-2" href="#" data-action="delete-${category.id}">删除此类</a></li>
              <li><hr class="dropdown-divider my-1"></li>
              <li><a class="dropdown-item px-3 py-2" href="#" data-action="add-${category.id}">添加子类</a></li>
            </ul>
          </div>
        </div>
        ${hasChildren ? `
          <div class="collapse children-container w-100" id="children-${category.id}">
            <ul class="list-group list-group-flush children-list ps-4">
              ${category.children.map(child =>
            renderCategory(child, selectedId, level + 1)).join('')}
            </ul>
          </div>` : ''
        }
      </li>`;
    }

    // 辅助函数9.:将商品数据渲染到模态框中并允许用户修改
    function fillProductForm(productData) {
        // 基本信息
        $('#productName').val(productData.name);
        $('#productDescription').val(productData.description);

        // 分类选择
        const categoryNames = (productData.categories || []).map(({name}) => name);  // 结果: ['分类一', '分类二']
        // const categoryId = (productData.categories || []).map(({id}) => id);  // 结果: [27, 28]
        // $('#categoryDropdown').text(categoryNames.join(', ') || '选择分类 (可多选)');
        $('#selectedCategories').text(`已选分类: ${categoryNames.join(', ')}`);

        // 商品属性参数
        const details = productData.details.map(item => {
            const [key, last_value] = Object.entries(item)[0]; // 获取第一个键值对
            return {key, last_value};
        });
        renderGrid(details || [])

        // 主图预览
        // const placeholder = document.querySelector('.preview-placeholder');
        // const placeholder = document.querySelector('.image-preview');
        // if (placeholder) placeholder.remove();  // 移除默认预览占位符
        // previewImages = []
        // currentImageIndex = 0
        productData.main_images.forEach(imageData => {
            previewImages.push(imageData);
            // renderPreviewImage(imageData);
            const previewItem = createPreviewItem(imageData)
            previewContainer.insertBefore(previewItem, uploadTrigger);
        })

        // 视频预览
        if (productData.video_url) {
            // 渲染带视频源的可点击播放器
            $('#videoPreview').html(`
          <div class="video-container" style="max-height:120px; width:auto; display:inline-block;">
            <video class="img-thumbnail"
              style="height:100%; width:auto; aspect-ratio:1/1; object-fit:contain; cursor:pointer"
            >
              <source src="${productData.video_url}" type="video/mp4">
            </video>
          </div>
        `);
            // 点击控制
            $('#videoPreview video').on('click', function () {
                this.paused ? this.play() : this.pause();
            });
        }

        // 详情描述
        if (productData.details) {
            $('#productDetails').val(productData.details);
        }

        // SKU数据
        renderSkuTable(productData.skus || []);

        // 价格和库存
        $('#originalPrice').val(productData.original_price);
        $('#productPrice').val(productData.price);
        $('#productStock').val(productData.stock);
    }

    // 辅助函数9.完整表单重置函数
    function resetProductForm() {
        // 重置标准表单元素
        $elements.productForm[0].reset();

        // 重置分类选择
        $('#categoryDropdown').text('选择分类 (可多选)');
        $('#selectedCategories').text('');
        $('#categoryTreeContainer').find('input[type="checkbox"]').prop('checked', false);

        // 重置属性值对
        $('.kv-grid').text('');

        // 重置主图上传和预览(删除原有的图片预览元素)
        previewImages = []
        currentImageIndex = 0
        clearBetween(previewContainer, uploadTrigger)

        // 重置视频上传和预览
        $elements.productVideo.val('');
        $('#videoFileNameDisplay').text('支持MP4格式');
        $('#videoPreview').html(`
        <div class="border rounded text-center p-4 text-muted preview-placeholder">
          <i class="bi bi-film fs-1"></i>
          <p class="mt-2 mb-0">视频预览区域</p>
        </div>
      `);

        // 重置SKU表格
        $('#skuTableBody').empty();

        // 重置详情图片
        $('#detailImages').val('');

        // 移除任何上传状态提示
        $('#uploadAlert, #uploadVideoAlert').addClass('d-none');

        // 重置表单模式标识
        $elements.productForm.removeData('product-id');
        $('.modal-title').first().text('新增商品');
        $('#submitProductBtn').text('保存商品');
    }

    // 辅助函数9. 10. :让模态框焦点回归正常
    function modalInert(id) {
        $(id).on('show.bs.modal', function () {
            this.removeAttribute('inert');
        }).on('hide.bs.modal', function () {
            this.setAttribute('inert', '');
        });
    }

    // 辅助函数9.将商品数据渲染到模态框中并允许用户修改->SKU表格渲染函数(未调试)
    function renderSkuTable(skus) {
        const $tbody = $('#skuTableBody');
        $tbody.empty();

        skus.forEach(sku => {
            const $template = $('#skuRowTemplate').html();
            const $row = $($template);

            // 填充SKU数据
            $row.find('.attribute-input').val(sku.attributes.join(', '));
            $row.find('.sku-price').val(sku.price);
            $row.find('.sku-stock').val(sku.stock);

            if (sku.image_url) {
                $row.find('.sku-image').parent().html(`
            <img src="${sku.image_url}" class="img-thumbnail" style="height:60px">
          `);
            }

            $tbody.append($row);
        });
    }

    // 辅助函数10. 19.预览商品图片->更新图片计数器
    function updateImageCounter() {
        const counter = document.getElementById('imageCounter');
        counter.textContent = `${currentImageIndex + 1} / ${previewImages.length}`;

        // 单张图片时隐藏导航箭头
        if (previewImages.length <= 1) {
            document.getElementById('prevBtn').style.display = 'none';
            document.getElementById('nextBtn').style.display = 'none';
        } else {
            document.getElementById('prevBtn').style.display = 'block';
            document.getElementById('nextBtn').style.display = 'block';
        }
    }

    // 辅助函数:10.商品行编辑->保存原始数据(暂未用)
    function saveOriginalData(row) {
        const productId = row.data('product-id');

        // 保存所有单元格内容
        const cells = {
            name: row.find('td:eq(2)').text(),
            stock: row.find('td:eq(3)').text(),
            price: row.find('td:eq(4)').text(),
            status: row.find('td:eq(5)').html(),
            actions: row.find('td:last-child').html()
        };

        // 保存到全局容器
        originalRowData.set(productId, {
            cells,
            timestamp: new Date().getTime()
        });

    }

    // 辅助函数:10.商品行编辑->恢复原始数据(暂未用)
    function restoreOriginalData(row, productId) {
        const originalData = originalRowData.get(productId);

        if (!originalData) {
            console.error(`找不到产品 ${productId} 的原始数据`);
            return;
        }

        // 恢复所有单元格内容
        row.find('td:eq(2)').text(originalData.cells.name);
        row.find('td:eq(3)').text(originalData.cells.stock);
        row.find('td:eq(4)').html(originalData.cells.price);
        row.find('td:eq(5)').html(originalData.cells.status);
        row.find('td:last-child').html(originalData.cells.actions);

        // 重新绑定事件
        row.find('.edit-product').click(editProductRow);

    }

    // 辅助函数16. 新增或修改商品之:+历史属性值->渲染网格
    function renderGrid(kvData) {
        kvGrid.innerHTML = '';
        if (kvData.length === 0) {
            kvData.push({key: '', last_value: ''}, {key: '', last_value: ''});
        }
        if (kvData.length % 2 === 1) {
            kvData.push({key: '', last_value: ''});
        }
        for (let i = 0; i < kvData.length; i += 2) {
            const item = kvData[i]
            const next_item = kvData[i + 1]
            const row = document.createElement('div');
            row.className = 'kv-row';

            // 检查键名是否重复
            const isDuplicate = checkKeyUniqueness(i, item.key);
            const isDuplicate_next = checkKeyUniqueness(i + 1, next_item.key);
            let row1 = ''
            let row2 = ''
            // 创建第一个键值对
            if (item) {
                // row.appendChild(createKVPair(row, index, item, isDuplicate));
                row1 = createKVPair(i, item, isDuplicate, 1);
                // kvGrid.appendChild(createKVPair(row, index, item, isDuplicate));
            }
            // 创建第二个键值对
            if (next_item) {
                row2 = createKVPair(i + 1, next_item, isDuplicate_next, 2);
                // kvGrid.before(createKVPair(row, index+1, next_item, isDuplicate_next));
            }
            row.innerHTML = row1 + row2
            kvGrid.appendChild(row)
        }
    }

    // 辅助函数16. 新增或修改商品之:+历史属性值->检查键名是否重复
    function checkKeyUniqueness(currentIndex, keyValue) {
        if (!keyValue) return false;

        return kvData.some((item, index) =>
            index !== currentIndex && item.key === keyValue
        );
    }

    // 辅助函数16. 新增或修改商品之:+历史属性值->渲染键值对
    function createKVPair(index, item, isDuplicate, spacing) {
        return `
        <div class="kv-controls">
            <button class="kv-btn remove-btn" data-index="${index}">-</button>
        </div>
        <div class="kv-key">
            <input type="text" class="key-input ${isDuplicate ? 'duplicate' : ''}" 
                   data-index="${index}" value="${item.key}" 
                   placeholder="属性名">
        </div>
        <span>:</span>       
        <div class="kv-value ${spacing === 1 ? 'me-3' : ''}">
            <input type="text" class="value-input" 
                   data-index="${index}" value="${item.last_value}" 
                   placeholder="值">
        </div>
    `;

    }

    // 辅助函数18.-> 删除键值对(半行)
    function removeRow(e) {
        const index = e.target.dataset.index
        kvGrid.innerHTML = '';
        kvData.splice(parseInt(index), 1);
        kvData = kvData.filter(item => item.key !== '' || item.last_value !== '');  // 去掉键值对都是空的
        renderGrid(kvData);
    }

    // 辅助函数20.上传主图->初始化图片预览功能
    function initImagePreview() {
        // 上一张按钮事件
        document.getElementById('prevBtn').addEventListener('click', () => {
            navigateImage(-1); // 向左导航
        });

        // 下一张按钮事件
        document.getElementById('nextBtn').addEventListener('click', () => {
            navigateImage(1); // 向右导航
        });

        // 键盘导航支持
        document.addEventListener('keydown', (e) => {
            const modal = document.getElementById('imagePreviewModal');
            if (!modal.classList.contains('show')) return;

            if (e.key === 'ArrowLeft') {
                navigateImage(-1);
            } else if (e.key === 'ArrowRight') {
                navigateImage(1);
            } else if (e.key === 'Escape') {
                bootstrap.Modal.getInstance(modal).hide();
            }
        });

        // 触摸滑动支持（移动端）
        const slider = document.getElementById('sliderContainer');
        let touchStartX = 0;

        slider.addEventListener('touchstart', (e) => {
            touchStartX = e.touches[0].clientX;
        });

        slider.addEventListener('touchend', (e) => {
            const touchEndX = e.changedTouches[0].clientX;
            const diffX = touchStartX - touchEndX;

            // 滑动距离超过50px才切换
            if (Math.abs(diffX) > 50) {
                if (diffX > 0) {
                    navigateImage(1); // 向左滑动，显示下一张
                } else {
                    navigateImage(-1); // 向右滑动，显示上一张
                }
            }
        });
    }

    // 辅助函数20.上传主图->初始化图片预览功能->图片导航函数->页面加载时初始化预览功能
    initImagePreview()

    // 辅助函数20.上传主图->初始化图片预览功能->图片导航函数
    function navigateImage(direction) {
        // 计算新索引
        currentImageIndex = (currentImageIndex + direction + previewImages.length) % previewImages.length;

        // 更新显示的图片
        const modalImage = document.getElementById('previewImage');
        modalImage.src = previewImages[currentImageIndex].src;

        // 更新计数器
        updateImageCounter();
    }

    // 辅助函数20.上传主图->多层模态框,最上层做防护,避免界面卡死
    function initializeModal(modalUpperLevelsId){
        $(modalUpperLevelsId).modal({
        backdrop: 'static', // 防止点击外部关闭
        keyboard: false    // 防止 ESC 关闭
        }).on('show.bs.modal', function () {
            // 冻结底层模态框
            $('#addProductModal').attr('inert', '').css('pointer-events', 'none');
        }).on('hidden.bs.modal', function () {
            // 恢复底层模态框
            $('#addProductModal').removeAttr('inert').css('pointer-events', 'auto');
        });
    }

    // 辅助函数20.上传主图->创建预览项
    function createPreviewItem(file=null) {
        const src = file ? file.src : ''
        const id = file ? file.id : Date.now() + Math.random().toString(36).substr(2, 9)
        const item = document.createElement('div');
        item.className = 'preview-item position-relative';
        item.draggable = true; // 使元素可拖动
        item.innerHTML = `
            <div class="upload-progress">
                <div class="progress-bar"></div>
            </div>
 
            <img src="${src}" alt="预览中..." class="img-fluid" id="${id}">
            
            <div class="preview-actions">
                <button class="btn btn-preview-action btn-sm btn-danger">
                    <i class="bi bi-x"></i>
                </button>
            </div>
            <div class="position-absolute bottom-0 start-0 end-0 bg-danger text-white small text-center preview-error"></div>
        `;

        // 拖动相关事件
        item.addEventListener('dragstart', handleDragStart);
        item.addEventListener('dragover', handleDragOver);
        item.addEventListener('dragleave', handleDragLeave);
        item.addEventListener('drop', handleDrop);
        item.addEventListener('dragend', handleDragEnd);

        // 删除按钮事件
        item.querySelector('.btn').addEventListener('click', (e) => {
            e.stopPropagation();
            // 从预览数组中移除
            const index = previewImages.findIndex(img => img.id.toString() === item.querySelector('img').id);
            if (index !== -1) {previewImages.splice(index, 1)}
            item.remove();
        });

        // 点击图片事件:预览图片
        item.querySelector('.img-fluid').addEventListener('click', (e) => {
            e.stopPropagation();
            // 找到当前图片在预览数组中的索引
            currentImageIndex = previewImages.findIndex(img => img.id.toString() === e.target.id);
            // 设置模态框图片
            const modalImage = document.getElementById('previewImage');
            modalImage.src = e.target.src;
            // 更新计数器
            updateImageCounter();
            // 让模态框焦点回归正常
            modalInert('#imagePreviewModal')
            // 打开模态框
            const modal = new bootstrap.Modal(document.getElementById('imagePreviewModal'));
            modal.show();
        });
        return item;
    }

    // 辅助函数20.上传主图->模拟上传进度
    function simulateUploadProgress(previewItem) {
        const progressBar = previewItem.querySelector('.progress-bar');
        let progress = 0;
        const interval = setInterval(() => {
            progress += 5;
            progressBar.style.width = `${progress}%`;

            if (progress >= 100) {
                clearInterval(interval);
                previewItem.querySelector('.upload-progress').remove();
            }
        }, 100);
    }

    // 辅助函数20.上传主图->显示裁剪对话框
    function showCropDialog(previewItem, file, imgSrc) {
        currentCropFile = {previewItem, file};
        cropperImage.src = imgSrc;
        cropModal.show();
        // 初始化Cropper
        setTimeout(() => {
            if (cropper) cropper.destroy();

            cropper = new Cropper(cropperImage, {
            aspectRatio: 1,
            viewMode: 1,
            autoCropArea: 1,
            responsive: true,
            guides: false
            // highlight: false
        });
      }, 200);
    }

    // 辅助函数20-4.上传主图:确认裁剪事件
    function confirmCrop(){
        // 获取裁剪后的图片
        cropper.getCroppedCanvas({
        width: MIN_WIDTH,
        height: MIN_HEIGHT,
        fillColor: '#fff',
        imageSmoothingEnabled: true,
        imageSmoothingQuality: 'high'
        }).toBlob((blob) => {
            // 更新预览
            const reader = new FileReader();
            reader.onload = (e) => {
                currentCropFile.previewItem.querySelector('img').src = e.target.result;
                currentCropFile.previewItem.classList.remove('border-danger');
                currentCropFile.previewItem.querySelector('.preview-error').textContent = '';
                simulateUploadProgress(currentCropFile.previewItem);
                // 加到预览列表中
                previewImages.push(currentCropFile.previewItem.querySelector('img'))

            };
            reader.readAsDataURL(blob);   // blob: {size: 62854, type: 'image/jpeg'}
            // 销毁Cropper实例
            if(cropper) {
                cropper.destroy();
                cropper = null;
            }
            cropModal.hide();
        }, 'image/jpeg', 0.9);
    }

    // 辅助函数20.上传主图->创建预览项->开始拖动
    function handleDragStart(e) {
        draggedItem = this;
        this.classList.add('dragging');
        e.dataTransfer.effectAllowed = 'move';
        // 设置拖拽数据为元素的id（如果没有可以设置其他标识）
        e.dataTransfer.setData('text/html', this.innerHTML);
    }

    // 辅助函数20.上传主图->创建预览项->放置位置
    function handleDragOver(e) {
        if (e.preventDefault) {
            e.preventDefault(); // 允许放置
        }
        e.dataTransfer.dropEffect = 'move';

        // 如果不是拖动的元素本身且不是上传按钮
        if (this !== draggedItem && !this.classList.contains('upload-card')) {
            this.classList.add('dropzone');
        }
        return false;
    }

    // 辅助函数20.上传主图->创建预览项->位置更换前的删除
    function handleDragLeave(e) {
        this.classList.remove('dropzone');
    }

    // 辅助函数20.上传主图->创建预览项->位置更换
    function handleDrop(e) {
        if (e.stopPropagation) {
            e.stopPropagation(); // 阻止事件冒泡
        }

        // 如果不是拖动的元素本身且不是上传按钮
        if (this !== draggedItem && !this.classList.contains('upload-card')) {
            // 交换两个元素的位置
            const parent = this.parentNode;
            const thisIndex = Array.from(parent.children).indexOf(this);
            const draggedIndex = Array.from(parent.children).indexOf(draggedItem);

            if (draggedIndex < thisIndex) {
                parent.insertBefore(draggedItem, this.nextSibling);
            } else {
                parent.insertBefore(draggedItem, this);
            }

            // 更新预览数组顺序
            updatePreviewImagesOrder();
        }

        this.classList.remove('dropzone');
        return false;
    }

    // 辅助函数20.上传主图->创建预览项->移除样式
    function handleDragEnd() {
        this.classList.remove('dragging');
        // 移除所有放置区域的样式
        document.querySelectorAll('.preview-item').forEach(item => {
            item.classList.remove('dropzone');
        });
    }

    // 辅助函数20.上传主图->创建预览项->更新预览图片数组顺序
    function updatePreviewImagesOrder() {
        previewImages = [];
        document.querySelectorAll('.preview-item img').forEach(img => {
            if (img.id) { // 确保是已上传的图片
                previewImages.push(img);
            }
        });
    }

    // 辅助函数20.上传主图->创建预览项->初始化时添加拖动事件到上传按钮（防止拖动时意外触发）
    uploadTrigger.addEventListener('dragover', (e) => {
        e.preventDefault();
        e.dataTransfer.dropEffect = 'none';
    });
    uploadTrigger.addEventListener('drop', (e) => {
        e.preventDefault();
    });

    // 辅助函数20.上传主图->清除预览区域
    function clearBetween(previewContainer, uploadTrigger) {
      const triggerIndex = Array.from(previewContainer.children).indexOf(uploadTrigger);
      Array.from(previewContainer.children).slice(0, triggerIndex).forEach(el => el.remove());
    }




    // ############################  其他辅助函数 #####################################
    // 获取CSRF Token的函数
    function getCSRFToken() {
        const csrftoken = document.cookie.match(/csrftoken=([^;]+)/)?.[1]
            || document.querySelector('meta[name="csrf-token"]')?.content;
        return csrftoken || '';
    }

    // 显示提示
    function showAlert(message, type) {
    const alert = document.createElement('div');
    alert.className = `alert alert-${type} alert-dismissible fade show position-fixed bottom-0 end-0 m-3`;
    alert.style.zIndex = 1100;
    alert.innerHTML = `
        ${message}
        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
    `;
    document.body.appendChild(alert);
    setTimeout(() => alert.remove(), 3000);
}


    // saveProduct(暂未用)
    function saveProduct(productData) {
        // 提交产品数据（新增/更新）
        const method = productData.id ? 'PUT' : 'POST';
        const url = productData.id ? `/api/products/${productData.id}` : '/api/products';

        $.ajax({
            type: method,
            url: url,
            contentType: "application/json",
            data: JSON.stringify(productData),
            success: () => {
                // abp.notify.info('产品保存成功');  // 成功提示
                // hideProductModal();               // 关闭模态框
                // refreshProductList();             // 刷新列表
            },
            error: (xhr) => {
                console.error("保存失败:", xhr.responseText);
            }
        });
    }

    // 添加SKU行
    document.getElementById('addSkuBtn').addEventListener('click', function () {
        const template = document.getElementById('skuRowTemplate');
        const clone = template.content.cloneNode(true);
        document.getElementById('skuTableBody').appendChild(clone);

        // 初始化新行的交互
        initSkuRow(document.querySelector('#skuTableBody tr:last-child'));
    });

    // 初始化SKU行交互
    function initSkuRow(row) {
        // 添加属性按钮
        row.querySelector('.add-attribute-btn').addEventListener('click', function () {
            const container = row.querySelector('.attributes-container');
            const input = row.querySelector('.attribute-input');

            if (input.value.trim() === '') return;

            const attribute = input.value.trim();
            const badge = document.createElement('span');
            badge.className = 'badge bg-primary me-2 mb-2';
            badge.textContent = attribute;

            const removeBtn = document.createElement('button');
            removeBtn.className = 'btn-close btn-close-white btn-close-sm ms-1';
            removeBtn.addEventListener('click', function () {
                badge.remove();
            });

            badge.appendChild(removeBtn);
            container.appendChild(badge);

            input.value = '';
        });

        // 删除SKU行
        row.querySelector('.remove-sku-btn').addEventListener('click', function () {
            row.remove();
        });
    }

    // 提交商品表单
    document.getElementById('submitProductBtn').addEventListener('click', function () {
        const form = document.getElementById('productForm');
        const formData = new FormData(form);

        // 收集SKU数据
        const skus = [];
        document.querySelectorAll('.sku-row').forEach(row => {
            const attributes = [];
            row.querySelectorAll('.attributes-container .badge').forEach(badge => {
                attributes.push(badge.textContent.replace('×', '').trim());
            });

            const sku = {
                attributes: attributes.join('>'),
                price: row.querySelector('.sku-price').value,
                stock: row.querySelector('.sku-stock').value,
                image: row.querySelector('.sku-image').files[0]
            };

            skus.push(sku);
        });

        // 添加SKU数据到FormData
        formData.append('skus', JSON.stringify(skus));

        // 发送AJAX请求
        fetch('/api/products/', {
            method: 'POST',
            body: formData,
            headers: {
                'X-CSRFToken': formData.get('csrfmiddlewaretoken')
            }
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    addProductModal.hide();
                    // 刷新商品列表或显示成功消息
                    showToast('商品添加成功', 'success');
                    // 这里可以添加刷新列表的逻辑
                } else {
                    showToast(data.message || '添加商品失败', 'danger');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                showToast('网络错误，请重试', 'danger');
            });
    });

    // 绑定行事件
    function attachRowEvents(row) {
        const keyInput = row.querySelector('.attribute-key');
        const valueInput = row.querySelector('.attribute-value');
        const removeBtn = row.querySelector('.remove-row');

        // 键输入自动填充最近值
        keyInput.addEventListener('change', function () {
            if (attributeHistory[this.value]) {
                valueInput.value = attributeHistory[this.value];
            }
            updateDetailsJson();
        });

        // 值变化时更新
        valueInput.addEventListener('input', updateDetailsJson);

        // 删除行
        removeBtn.addEventListener('click', function () {
            row.remove();
            updateDetailsJson();
        });
    }

    // 更新隐藏字段
    function updateDetailsJson() {
        const rows = tableBody.querySelectorAll('tr');
        const details = [];

        rows.forEach(row => {
            const key = row.querySelector('.attribute-key').value.trim();
            const value = row.querySelector('.attribute-value').value.trim();

            if (key) {
                details.push({[key]: value});
            }
        });

        detailsJson.value = JSON.stringify(details);
    }

    // 清除本地存储
    function clearLocalStorage() {
        if (confirm('确定要清除所有存储数据吗？此操作不可撤销。')) {
            localStorage.removeItem('keyValuePairs');
            kvData = [];
            renderGrid();
        }
    }

    // 导出数据
    function exportData() {
        const dataStr = JSON.stringify(kvData, null, 2);
        const blob = new Blob([dataStr], {type: 'application/json'});
        const url = URL.createObjectURL(blob);

        const a = document.createElement('a');
        a.href = url;
        a.download = 'key_value_data.json';
        document.body.appendChild(a);
        a.click();

        setTimeout(() => {
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        }, 0);
    }

    // 自动填充值
    function autoFillValue(currentIndex, keyValue) {
        if (!keyValue) return;

        const matchingItem = kvData.find((item, index) =>
            index !== currentIndex && item.key === keyValue
        );

        if (matchingItem) {
            const row = kvGrid.children[currentIndex];
            const valueInput = row.querySelector('.kv-value input');

            // 仅当值输入框为空时才自动填充
            if (!valueInput.value.trim()) {
                valueInput.value = matchingItem.value;
                kvData[currentIndex].value = matchingItem.value;
                // saveToLocalStorage();

                // 显示提示
                const statusBar = document.querySelector('.auto-save-notice');
                const originalText = statusBar.textContent;
                statusBar.textContent = `已自动填充值: "${matchingItem.value}"`;

                setTimeout(() => {
                    statusBar.textContent = originalText;
                }, 2000);
            }
        }
    }

    // 更新本地存储状态显示
    function updateStorageStatus() {
        const savedData = localStorage.getItem('keyValuePairs');
        const hasData = savedData && savedData !== '[]';

        // clearStorageBtn.disabled = !hasData;
        // exportDataBtn.disabled = !hasData;
        // updateItemCount();
    }

    // HTML转义防止XSS
    function escapeHtml(str) {
        return str.replace(/[&<>"']/g,
            tag => ({
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#39;'
            }[tag] || tag));
    }

    // 添加新行函数
    function addAttributeRow(key = '', value = '') {
        const row = document.createElement('tr');
        row.innerHTML = `
        <td>
            <input type="text" class="form-control form-control-sm attribute-key"
                   list="attributeKeys" value="${key}">
        </td>
        <td>
            <input type="text" class="form-control form-control-sm attribute-value"
                   value="${value}">
        </td>
        <td class="text-center">
            <button type="button" class="btn btn-sm btn-outline-danger remove-row">
                <i class="bi bi-trash"></i>
            </button>
        </td>
    `;
        tableBody.appendChild(row);
        attachRowEvents(row);
        updateDetailsJson();
        return row;
    }

    // 表单提交前确保更新
    document.querySelector('form').addEventListener('submit', () => {
        updateDetailsJson();
    });

    // 通过Django模板注入初始化数据(暂未用)
    document.addEventListener('DOMContentLoaded', function () {
        // 通过Django模板注入初始化数据
        const initDetails = JSON.parse('{{ details_json|escapejs }}');

        // if (initDetails.length > 0) {
        //     initDetails.forEach(item => {
        //         const [key, value] = Object.entries(item)[0];
        //         addAttributeRow(key, value);
        //     });
        // } else {
        //     addAttributeRow(); // 空行
        // }
    });

}
})();
